/*
* =====================================================================================
*
*       Filename:  gdbus_client.c
*
*    Description:
*
*        Version:  1.0
*        Created:  02/17/2017 08:28:34 AM
*       Revision:  none
*       Compiler:  gcc
*
*         Author:  qiaotsh (), qiaotsh@neusoft.com
*   Organization:  www.neusoft.com
*
* =====================================================================================
*/
#include<stdio.h>
#include<gio/gio.h>
#include<glib.h>
#include<assert.h>
#include<fcntl.h>
#include<libusb.h>
#include <pthread.h>
#include<sys/time.h>

#include "common.h"
#include "ofprint_common.h"
#include "app_fp256_360.h"
#include "usb_device.h"
#include"ofprint-server.h"
#include "upgrade.h"
#include "usb_device.h"

static int PRINTF_LOG_GRADE = 0;

static GMainLoop *pLoop = NULL;
static OfprintSkeleton* pSkeleton=NULL;
static int logfileFD = 0;


char **finger_name;

OFP_ENROLL_STATUS_CALLBACK ofp_enroll_status_callback = NULL;
OFP_VERIFY_STATUS_CALLBACK ofp_verify_status_callback = NULL;
OFP_TOUCH_CALLBACK ofp_touch_callback = NULL;
OFP_IDENTIFY_WITH_MULTIPLE_USER_STATUS_CALLBACK ofp_identify_with_multiple_user_status_callback = NULL;


static int32 usb_lib_init(ofp_dev * dev)
{
    int32 ret = libusb_init(&(dev->ctx));
    if(0 > ret)
    {
        return -1;
    }
    pthread_mutex_init(&(dev->usb_mutex), NULL);
    pthread_mutex_init(&(dev->hotplug_mutex), NULL);
    pthread_mutex_init(&(dev->usb_bulk_mutex), NULL);

    return 0;
}


static void usb_lib_exit(ofp_dev * dev)
{
    libusb_exit(dev->ctx);
    pthread_mutex_destroy(&(dev->usb_mutex));
    pthread_mutex_destroy(&(dev->hotplug_mutex));
    pthread_mutex_destroy(&(dev->usb_bulk_mutex));

}


/********** 外部函数实现 **********/
char * ofp_new_string(char * old_str){
    char * str = NULL;

    if (old_str == NULL) {
        str = malloc(1);
        if (str != NULL)
            *str = '\0';
    } else {
        int l = strlen(old_str) + 1;
        str = malloc(l);
        if (str != NULL)
        {
            memset(str, 0x00, l);
            //strncpy(str, old_str, l);
            memcpy(str, old_str, strlen(old_str));
            str[strlen(old_str)] = '\0';
        }
    }

    return str;
}


int set_printf_log_grade(int flag)
{
    PRINTF_LOG_GRADE = flag;
    return 0;
}

int get_printf_log_grade(void)
{
    return PRINTF_LOG_GRADE;
}

//add by hcq, 20220331 12:00
int ofp_print_log(char *buf, int len, LOG_GRADE_ENUM grade)
{
#if 0
    int logfileFD = 0;

    if((NULL == buf) || (0 == len))
        return -1;

    if(grade > get_printf_log_grade())
        return -1;

    if((logfileFD = open(OFP_LOG_FILE_NAME, O_RDWR|O_CREAT|O_APPEND, 0666))<0)
    {
        printf("open logfile %s: failed!!!\n", OFP_LOG_FILE_NAME);
        return -1;
    }

    if(len != write(logfileFD, buf, len))
        printf("write logfile %s: ERROR!!!\n", OFP_LOG_FILE_NAME);

    close(logfileFD);
#endif
    return 0;
}

//add by hcq, 20220331 12:00
int ofp_print_log_time(char *buf, int len, LOG_GRADE_ENUM grade)
{
#if 0
    int logfileFD = 0;

    if((NULL == buf) || (0 == len))
        return -1;

    if(grade > get_printf_log_grade())
        return -1;

    if((logfileFD = open(OFP_LOG_FILE_NAME, O_RDWR|O_CREAT|O_APPEND, 0666))<0)
    {
        printf("open logfile %s: failed!!!\n", OFP_LOG_FILE_NAME);
        return -1;
    }

    time_t current_time = time(NULL);//获取时间戳
    struct tm *local_time = localtime(&current_time);//将时间戳转换为本地时间
    char str_time[100] = {0};
    snprintf(str_time, 100, "%04d%02d%02d_%02d:%02d:%02d ",
                            local_time->tm_year+1900, local_time->tm_mon+1, local_time->tm_mday,
                            local_time->tm_hour, local_time->tm_min, local_time->tm_sec);

    if(strlen(str_time) != write(logfileFD, str_time, strlen(str_time)))
        printf("write logfile %s: ERROR!!!\n", OFP_LOG_FILE_NAME);

    if(len != write(logfileFD, buf, len))
        printf("write logfile %s: ERROR!!!\n", OFP_LOG_FILE_NAME);

    close(logfileFD);
#endif
    return 0;
}

int check_log_file_size(void)
{
    if(LOG_FILE_SIZE_MAX > com_get_file_size(OFP_LOG_FILE_NAME))
        return 0;

    char str_cmd[500];
    snprintf(str_cmd, 500,  "mv -f %s %s.bak", OFP_LOG_FILE_NAME, OFP_LOG_FILE_NAME);
    if(0 > system(str_cmd))
        WD_ERR("exec failed!\n");

    return 0;
}



int ofp_vprint_by_level(int print_level, FILE * __restrict stream,
                        const char * __restrict format, va_list args)
{
    int ret = 0;
    int level_int = 0;

    switch (print_level)
    {
        case OFP_PRINT_LEVEL_EMERG:
            fprintf(stderr, "[EMERG] ");
            break;
        case OFP_PRINT_LEVEL_ALERT:
            fprintf(stderr, "[ALERT] ");
            break;
        case OFP_PRINT_LEVEL_CRIT:
            fprintf(stderr, "[ CRIT] ");
            break;
        case OFP_PRINT_LEVEL_ERROR:
            fprintf(stderr, "[ERROR] ");
            break;
        case OFP_PRINT_LEVEL_WARN:
            fprintf(stdout, "[ WARN] ");
            break;
        case OFP_PRINT_LEVEL_NOTICE:
            fprintf(stdout, "[ NOTE] ");
            break;
        case OFP_PRINT_LEVEL_INFO:
            fprintf(stdout, "[ INFO] ");
            break;
        case OFP_PRINT_LEVEL_DEBUG:
            fprintf(stdout, "[DEBUG] ");
            break;
        default:
            fprintf(stdout, "[UKNOW] ");
    }

    ret = vfprintf(stream, format, args);

    fflush(stream);

    return ret;
}

int ofp_print_info(const char * format, ...)
{
    int ret = 0;
    va_list args;

    va_start(args, format);
    ret = ofp_vprint_by_level(OFP_PRINT_LEVEL_INFO, stdout, format, args);
    va_end(args);

    return ret;
}

int ofp_ops_cancel(ofp_dev * dev)
{
    driver_info *priv = (driver_info *)dev->dev_priv;
    FP_DEVICE_PARAM_STRUCT *dev_param = &(priv->fp_device_param);
    USB_DEV_STRUCT *usb_dev = &(dev_param->usb_dev);
    INTF_USB_ID_STRUCT *id_table = (INTF_USB_ID_STRUCT *)(dev->usb_info.id_table);

    WD_DBG("start.\n");

    if (dev->enable == FALSE) {       // 设备不可用
        ofp_set_dev_status(dev, DEVS_COMM_DISABLE);
        return -1;
    }

    if(NULL == usb_get_dev_handle(usb_dev))
    {
        usb_dev_open(usb_dev, id_table);
    }

    fp_cancel(dev_param);
    //fp_read_invalid_pkg(dev_param, 3);//规避取消报文错位，add by hcq, 20230314

    usb_dev_close(usb_dev);

    WD_DBG("end.\n");

    return 0;
}

int ofp_set_mode(ofp_dev *dev)
{
    driver_info *priv = (driver_info *)dev->dev_priv;
    FP_DEVICE_PARAM_STRUCT *dev_param = &(priv->fp_device_param);
    USB_DEV_STRUCT *usb_dev = &(dev_param->usb_dev);
    INTF_USB_ID_STRUCT *id_table = (INTF_USB_ID_STRUCT *)(dev->usb_info.id_table);

    int mode_flag = priv->mode_flag;

    if((NULL == usb_get_dev_handle(usb_dev)) && (DRV_OK != usb_dev_open(usb_dev, id_table)))
    {
        D_DBG("can't open device!!!\n");
        return -1;
    }

    D_DBG("mode_flag = %d\n", mode_flag);

    if(OFP_DEBUG_MODE_FLAG == mode_flag)
    {
        D_DBG("set OFP_DEBUG_MODE_FLAG.\n");
        fp_set_mode(dev_param, FP_DEBUG_MODE_FLAG, strlen(FP_DEBUG_MODE_FLAG));
    }
    else if(OFP_USER_MODE_FLAG == mode_flag)
    {
        D_DBG("set OFP_USER_MODE_FLAG.\n");
        fp_set_mode(dev_param, FP_USER_MODE_FLAG, strlen(FP_USER_MODE_FLAG));
    }

    usb_dev_close(usb_dev);

    D_DBG("end\n");

    return 0;
}


int ofp_set_reboot(ofp_dev *dev)
{
    driver_info *priv = (driver_info *)dev->dev_priv;
    FP_DEVICE_PARAM_STRUCT *dev_param = &(priv->fp_device_param);
    USB_DEV_STRUCT *usb_dev = &(dev_param->usb_dev);
    INTF_USB_ID_STRUCT *id_table = (INTF_USB_ID_STRUCT *)(dev->usb_info.id_table);
    int reboot_flag = priv->reboot_flag;
    DBG("ofp_set_reboot===================>enter\n");
    D_DBG("start, reboot_flag = %d\n", reboot_flag);

    if(OFP_SET_REBOOT_FLAG != reboot_flag)
    {
        DBG("ofp_set_reboot<===================not reboot exit\n");
        return 0;
    }

    if((NULL == usb_get_dev_handle(usb_dev)) && (DRV_OK != usb_dev_open(usb_dev, id_table)))
    {
        D_DBG("can't open device!!!\n");

        DBG("ofp_set_reboot<===================error exit\n");
        return -1;
    }

    fp_reboot(dev_param);

    usb_dev_close(usb_dev);
    DBG("ofp_set_reboot<===================exit\n");

    return 0;
}


/*
 * 删除无效指纹（模组中存在，数据库中不存在）
*/
int ofp_delete_invalid_feature(ofp_dev *dev)
{
    driver_info *priv = (driver_info *)dev->dev_priv;
    FP_DEVICE_PARAM_STRUCT *dev_param = &(priv->fp_device_param);

    WD_DBG("start.\n");

    if (dev->enable == FALSE) {
        WD_ERR("ofprint-serverd not enable!!!\n");
        return -1;
    }

    fprint_info *fprint_list = priv->fprint_list;
    uint8 index_table_info[INDEX_PAGE_NUM][32] = {{0}};

    if(0 != ofp_get_fprint_list(dev))
    {
        WD_ERR("ofp_get_fprint_list failed!!!\n");
        return -1;
    }

    // 读取特征列表
    for(int i = 0; i < OFP_FPRINT_NUM_MAX; i++)
    {
        if(TRUE == fprint_list[i].enable)
        {
            uint16 fprint_id = fprint_list[i].fprint_id;

            if(FP_ENROLL_ID_MAX >= fprint_id)
            {
                index_table_info[fprint_id/256][(fprint_id%256)/8] |= (0x01 << (fprint_id%8));
            }
        }
    }

    WD_DBG("********========print index_table_info\n");
    for(int line = 0; line < INDEX_PAGE_NUM; line++)
    {
        for(int16 i = 0; i < 32; i++)
        {
            W_DBG("%02x ", index_table_info[line][i]);
        }
        W_DBG("\r\n");
    }
    fp_delete_invalid_template(dev_param, (uint8 *)index_table_info);

    return 0;
}

int ofp1234_upgrade_pt(ofp_dev *dev, int dev_exit_flag)
{
    int upgrade_ret = -1;
    int ret = -1;
    USB_DEV_STRUCT *usb_dev = NULL;
    INTF_USB_ID_STRUCT *id_table;
    FP_DEVICE_PARAM_STRUCT *fp_device_param;
    driver_info *priv = dev->dev_priv;

    //WD_LOG("Please wait for upgrade firmware...\n");
    //WD_LOG("升级固件中，请等待...\n");

    DBG("ofp1234_upgrade_pt =============================>enter \n");
    WD_LOG("Try to upgrade firmware...\n");

    usb_dev = &(priv->fp_device_param.usb_dev);
    id_table = (INTF_USB_ID_STRUCT *)(dev->usb_info.id_table);
    fp_device_param = &(priv->fp_device_param);

    if(0 == dev_exit_flag)
    {
        if(0 != upgrade_check_boot_mcu_type())
        {
            WD_ERR("upgrade_check_boot_mcu_type: FAIL!\n");
            goto END;
        }

        upgrade_ret = upgrade_and_run();
        if(0 == upgrade_ret)
        {
            WD_LOG("UPGRADE: PASS.\n");
            change_fw_upgrade_flag();
            usleep(1000 * 1000);
            ret = 0;
            goto END;
        }
        else if(-2 == upgrade_ret)
        {
            ret = -2;
            goto END;
        }
    }
    else
    {
        for(int i = 0; i < 10; i++)//未识别到设备，循环超过10秒则退出
        //for(int i = 0; i < 6; i++)//未识别到设备，循环超过6秒则退出
        {
            if(DRV_OK == usb_dev_open(usb_dev, id_table))//规避模组不能一次复位成功问题，add by hcq, 20230425
            {
                fp_reboot(fp_device_param);
                usb_dev_close(usb_dev);
                //usleep(1000 * 1000);
            }

            usleep(1000 * 1000);

            if(0 != upgrade_check_boot_mcu_type())
            {
                WD_DBG("upgrade_check_boot_mcu_type: FAIL!\n");
                sleep(1);
                continue;
            }

            upgrade_ret = upgrade_and_run();
            if(0 == upgrade_ret)
            {
                WD_LOG("UPGRADE: PASS.\n");
                change_fw_upgrade_flag();
                usleep(1000 * 1000);
                ret = 0;
                goto END;
            }
            else if(-2 == upgrade_ret)
            {
                ret = -2;
                goto END;
            }
        }
    }

END:
    DBG("ofp1234_upgrade_pt <=============================ret = %d  exit \n", ret);
    return ret;
}


static int32 ofp1234_check_firmware_version(ofp_dev *dev)
{
    int ret = -1;
    driver_info *priv = (driver_info *)dev->dev_priv;
    USB_DEV_STRUCT *usb_dev;
    FP_DEVICE_PARAM_STRUCT *dev_param;
    INTF_USB_ID_STRUCT *id_table;

    DBG("ofp1234_check_firmware_version ==============> enter\n");
    WD_LOG("start.\n");

    dev_param = &(priv->fp_device_param);
    usb_dev = &(dev_param->usb_dev);
    id_table = (INTF_USB_ID_STRUCT *)(dev->usb_info.id_table);

    if((NULL == usb_get_dev_handle(usb_dev)) && (DRV_OK != usb_dev_open(usb_dev, id_table)))
    {
        WD_ERR("can't open device!!!\n");
        return -1;
    }

    if(DRV_OK != fp_get_firmware_version(dev_param))
    {
        WD_ERR("fp_get_firmware_version: FAIL!!!\n");
        goto END;
    }
    ret = 0;
END:
    usb_dev_close(usb_dev);
    DBG("ofp1234_check_firmware_version ==============> exit\n");

    return ret;
}

static gboolean ofp1234_need_upgrade(ofp_dev *dev)
{
    gboolean ret = FALSE;
    driver_info *priv = (driver_info *)dev->dev_priv;
    FP_DEVICE_PARAM_STRUCT *dev_param;
    USB_DEV_STRUCT *usb_dev;
    uint32 curr_ver_num = 0;
    uint32 new_ver_num = 0;
    UPGRADE_MODE_TYPE upgrade_mode = priv->config.upgrade_mode;
    int upgrade_flag = priv->config.upgrade_flag;
    char *file_path = NULL;
    DBG("ofp1234_need_upgrade ===========================>enter\n");
    WD_DBG("start\n");

    dev_param = &(priv->fp_device_param);
    usb_dev = &(dev_param->usb_dev);

    curr_ver_num = fp_return_firmware_version_num(dev_param);
    if(0 == curr_ver_num)
    {
        WD_ERR("firmware_version_num = %d, ERROR!!!\n", curr_ver_num);
        goto END;
    }

    if(DEVICE_THM36 == usb_dev_get_mcu_type(usb_dev))
    {
        new_ver_num = thm36_fw_upgrade_info()->fw_version_num;
        file_path = thm36_fw_upgrade_info()->file_path;
        WD_LOG("thm36 fw version = V%d, new fw version = V%d\n", curr_ver_num, new_ver_num);
    }
    else if(DEVICE_CCM4201S == usb_dev_get_mcu_type(usb_dev))
    {
        new_ver_num = ccm4201_fw_upgrade_info()->fw_version_num;
        file_path = ccm4201_fw_upgrade_info()->file_path;
        WD_LOG("ccm4201 fw version = V%d, new fw version = V%d\n", curr_ver_num, new_ver_num);
    }
    else if(DEVICE_ACM32 == usb_dev_get_mcu_type(usb_dev))
    {
        new_ver_num = acm32_fw_upgrade_info()->fw_version_num;
        file_path = acm32_fw_upgrade_info()->file_path;
        WD_LOG("acm32 fw version = V%d, new fw version = V%d\n", curr_ver_num, new_ver_num);
    }
    else
    {
        WD_ERR("usb_dev_get_mcu_type() = %d, ERROR!!!\n", usb_dev_get_mcu_type(usb_dev));
        goto END;
    }

    if(DONT_UPGRADE == upgrade_mode)
    {
        WD_LOG("forbid upgrade.\n");
        goto END;
    }

    if(0 >= upgrade_flag)
    {
        WD_LOG("upgrade_flag = %d, don't need upgrade.\n", upgrade_flag);
        goto END;
    }

    if(0 >= new_ver_num)
    {
        WD_ERR("new_ver_num = %d, ERROR!!!\n", new_ver_num);
        goto END;
    }

    if(((AUTO_UPGRADE == upgrade_mode) && (curr_ver_num != new_ver_num))\
        || ((SMART_UPGRADE == upgrade_mode) && (curr_ver_num < new_ver_num))\
        || (FORCE_UPGRADE == upgrade_mode))
    {
        if(0 == com_check_file_exit(file_path, FW_FILE_SIZE_MIN, FW_FILE_SIZE_MAX))
        {
            ret = TRUE;
            WD_LOG("need upgrade.\n");
        }
    }
    else
    {
        WD_LOG("don't need upgrade.\n");
        change_fw_upgrade_flag();
    }
END:
    DBG("ofp1234_need_upgrade <===========================exit\n");
    return ret;
}


static void ofprint_upgrade_pt(void)
{
    ofp_dev * dev = dev_ofprint;

    if(NULL == dev)
        return;

    ofp1234_upgrade_pt(dev, 1);
}

static int ofp1234_fw_version_manager(ofp_dev *dev)
{
    DBG("ofp1234_fw_version_manager ============>enter\n");
    int ret = -1;
    pthread_t thr_upgrade;

    if(0 != ofp1234_check_firmware_version(dev))
        goto end;

    if(TRUE != ofp1234_need_upgrade(dev))
        goto end;

    if(0 != ofp_set_reboot(dev))
        goto end;

    set_upgrade_state(1);
    sleep(2);
    ret = pthread_create(&thr_upgrade, NULL, (void *)ofprint_upgrade_pt, NULL);
    if (ret != 0)
        WD_ERR("Can't create thread: %s\n", strerror(ret));

end:
    DBG("ofp1234_fw_version_manager <============exit\n");
    return ret;
}



static gboolean gdbus_handle_claim(OfprintSkeleton* skeleton,
                                    GDBusMethodInvocation *invocation,
                                    char *id, gboolean claimed)
{
    ofp_dev *dev = dev_ofprint;
    DBG("gdbus_handle_claim ========================>enter\n");
    if (dev->enable == FALSE) {
        WD_ERR("ofprint-serverd not enable!!!\n");
        //ofprint_set_state(pSkeleton, 0);
        ofprintx_complete_claim(skeleton, invocation);
        return TRUE;
    }

    driver_info *priv = (driver_info *)dev->dev_priv;

    if(NULL != id)
    {
        strcpy(priv->user_id, id);
    }

    int timeuse = 0;
    while(DEVS_COMM_IDLE != ofp_get_dev_status(dev))
    {
        usleep(10 * 1000);
        timeuse+=10;
        if(3000 < timeuse)
            break;
    }

    if(TRUE == claimed)
    {
        WD_DBG("claim the device start.\n");

        priv->dev_state |= DeviceStateClaimed;
        priv->set_dev_state(priv->dev_state);

        //ofp_set_dev_status (dev, DEVS_OPEN_DOING);                        //设备状态设置为：正在打开设备

        // 私有结构体控制变量成员设置为:CONTROL_FLAG_RUNNING
        //priv->ctrlFlag = CONTROL_FLAG_RUNNING;
        //fp_set_ctrlFlag(0);

        //fp_handshake();
        // 设置状态
        //ofp_set_dev_status (dev, DEVS_COMM_IDLE);                    //当前状态设置为：空闲状态
        //ofp_set_ops_abs_result (dev, OPS_OPEN_SUCCESS);              //操作结果设置为：打开设备成功
        //ofp_set_notify_abs_mid (dev, NOTIFY_OPEN_SUCCESS);           //提示消息设置为：打开设备成功
        WD_DBG("claim the device end.\n");
    }
    else
    {
        WD_DBG("release the device start.\n");
        priv->dev_state &=~ DeviceStateClaimed;
        priv->set_dev_state(priv->dev_state);

        //priv->ctrlFlag == CONTROL_FLAG_IDLE;
        //usb_dev_close();
        //ofp_set_dev_status (dev, DEVS_COMM_IDLE);                    //当前状态设置为：空闲状态
        //ofp_set_ops_abs_result (dev, OPS_CLOSE_SUCCESS);              //操作结果设置为：关闭设备成功
        //ofp_set_notify_abs_mid (dev, NOTIFY_CLOSE_SUCCESS);           //提示消息设置为：关闭设备成功
        WD_DBG("release the device end.\n");
    }

    DBG("gdbus_handle_claim ========================>exit\n");
    ofprintx_complete_claim(skeleton, invocation);

    return TRUE;
}

void gdbus_enroll_pt(GSList * argv)
{
    OfprintSkeleton **p0;
    GDBusMethodInvocation **p1;
    char *p2;
    char *p3;
    DBG("gdbus_enroll_pt========================>enter\n");
    p0 = g_slist_nth_data(argv,0);
    p1 = g_slist_nth_data(argv,1);
    p2 = g_slist_nth_data(argv,2);
    p3 = g_slist_nth_data(argv,3);

    OfprintSkeleton *skeleton = (OfprintSkeleton *)*p0;
    GDBusMethodInvocation *invocation = (GDBusMethodInvocation *)*p1;
    char *id = p2;
    char *finger = p3;
    ofp_dev *dev = dev_ofprint;
    driver_info *priv = (driver_info *)dev->dev_priv;
    FP_DEVICE_PARAM_STRUCT *dev_param = &(priv->fp_device_param);
    USB_DEV_STRUCT *usb_dev = &(dev_param->usb_dev);
    INTF_USB_ID_STRUCT *id_table = (INTF_USB_ID_STRUCT *)(dev->usb_info.id_table);

    uint16 enroll_id = 0xffff;
    int32 timeout_ms = priv->timeoutMS;
    char msg_info[OFP_MSG_SIZE_MAX] = {0};


    WD_LOG("start.\n");
    ofprintx_complete_enroll(skeleton, invocation);

    if((dev->enable == FALSE) || (0 >= dev->dev_num))
    {
        ofp_enroll_status_callback(id, OFP_ENROLL_STAGE_DISCONNECTED, "{}");
        goto GDBUS_ENROLL_PT_END;
    }

    if(DEVS_COMM_IDLE != ofp_get_dev_status(dev))//设备非空闲状态
    {
        //ofprint_complete_enroll(skeleton, invocation);
        memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
        snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}\n", 1); //未知错误
        ofp_enroll_status_callback(id, OFP_ENROLL_STATUS_FAILED, msg_info);
        goto GDBUS_ENROLL_PT_END;
    }

    if((NULL == usb_get_dev_handle(usb_dev)) && (DRV_OK != usb_dev_open(usb_dev, id_table)))
    {
        ofp_enroll_status_callback(id, OFP_ENROLL_STAGE_DISCONNECTED, "{}");//返回设备失联
        goto GDBUS_ENROLL_PT_END;
    }

    ofp_set_dev_status (dev, DEVS_ENROLL_DOING);                           //设备状态设置为：正在录入
    fp_read_invalid_pkg(dev_param, 5);//规避读取固件报文错位问题，add by hcq, 20230607 13:30

    if(0 != ofp_delete_invalid_feature(dev))
    {
        WD_ERR("ofp_delete_invalid_feature failed!!!\n");
    }

    enroll_id = fp_get_empty_enroll_id(dev_param);
    if(FP_ENROLL_ID_MAX < enroll_id)
    {
        snprintf(priv->extra_info, EXTRA_INFO_LENGTH, \
                "Enroll failed ! Storage space is full.\n");// 用户提醒消息：指纹存储已满
        WD_ERR("%s", priv->extra_info);
        memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
        snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}", 4); //数据满了，不能再录制更多指纹
        ofp_enroll_status_callback(id, OFP_ENROLL_STATUS_FAILED, msg_info);
        goto GDBUS_ENROLL_PT_END;
    }

    WD_DBG("enroll_id = %d\n", enroll_id);

    //ofprint_complete_enroll(skeleton, invocation);
    snprintf(priv->extra_info, EXTRA_INFO_LENGTH, "enroll start ! Please press your finger.\n");
    //ofp_set_notify_abs_mid (dev, MID_EXTENDED_MESSAGE);
    WD_DBG("%s", priv->extra_info);
    memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
    snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"progress\":%d}", 0);//录入进度
    ofp_enroll_status_callback(id, OFP_ENROLL_STAGE_PASSED, msg_info);//开始录入

    uint16 identify_result_id[ENROLL_NUM_MAX];

check_whether_finger_exist:
    memset((char *)identify_result_id, 0xff, sizeof(identify_result_id));

    if((DRV_OK != fp_auto_identify(dev_param, 3, 0xffff, FP_CURRENT_OS_TYPE, identify_result_id, 0))
        && (PROT_RESP_FPRINTLIB_EMPTY != fp_get_identify_validity_check_result(dev_param)))
    {
        switch(fp_get_ctrlFlag(dev_param))
        {
            case FP_CONTROL_FLAG_STOPPED:
                WD_DBG("FP_CONTROL_FLAG_STOPPED\n");
                memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
                snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}", 3); //录入中断
                ofp_enroll_status_callback(id, OFP_ENROLL_STATUS_FAILED, msg_info);
                break;
            case FP_CONTROL_FLAG_TIMEOUT:
                WD_DBG("FP_CONTROL_FLAG_TIMEOUT\n");
                memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
                snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}", 3); //录入中断，是否有超时状态？
                ofp_enroll_status_callback(id, OFP_ENROLL_STATUS_FAILED, msg_info);
                break;
            case FP_CONTROL_FLAG_DEV_NOT_EXIST:
                ofp_enroll_status_callback(id, OFP_ENROLL_STAGE_DISCONNECTED, "{}");//设备失联
                WD_DBG("FP_CONTROL_FLAG_DEV_NOT_EXIST\n");
                break;
            default:
                WD_DBG("OPS_VERIFY_ERROR\n");
                memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
                snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}\n", 1); //未知错误
                ofp_enroll_status_callback(id, OFP_ENROLL_STATUS_FAILED, msg_info);
                break;
        }

        fp_cancel(dev_param);
        fp_set_ctrlFlag(dev_param, FP_CONTROL_FLAG_IDLE);
        goto GDBUS_ENROLL_PT_END;
    }

    for(int n = 0; n < ENROLL_NUM_MAX; n++)
    {
        if(0xffff == identify_result_id[n])
        {
            break;
        }

        if((CURRENT_ENROLL_ID_MIN <= identify_result_id[n]) && (CURRENT_ENROLL_ID_MAX >= identify_result_id[n]))
        {
            WD_LOG("identify_result_id %d is existed.\n", identify_result_id[n]);
            memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
            snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}\n", 4); //当前指纹已经存在，请换其他的手指
            ofp_enroll_status_callback(id, OFP_ENROLL_STAGE_RETRY, msg_info);
            goto check_whether_finger_exist;
        }
    }

    if(PROT_RESP_FPRINTLIB_EMPTY != fp_get_identify_validity_check_result(dev_param))
    {
        memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
        snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"progress\":%d}", 1 * (100/(dev->sample_times+1)));//录入进度
        ofp_enroll_status_callback(id, OFP_ENROLL_STAGE_PASSED, msg_info);
    }

    if(DRV_OK != fp_auto_enroll_start(dev_param, enroll_id, 6, 0))
    {
        //ofprint_complete_enroll(skeleton, invocation);
        switch(fp_get_ctrlFlag(dev_param))
        {
            case FP_CONTROL_FLAG_ENROLLID_OUT_RANGE:
                WD_DBG("Enroll failed ! Storage space is full.\n");// 用户提醒消息：指纹存储已满;
                memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
                snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}", 4); //数据满了，不能再录制更多指纹
                ofp_enroll_status_callback(id, OFP_ENROLL_STATUS_FAILED, msg_info);
                break;
            default:
                memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
                snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}\n", 1); //未知错误
                ofp_enroll_status_callback(id, OFP_ENROLL_STATUS_FAILED, msg_info);
                break;
        }
        fp_cancel(dev_param);
        //fp_read_invalid_pkg(dev_param, 5);//规避取消报文错位，add by hcq, 20230314

        goto GDBUS_ENROLL_PT_END;
    }



    WD_DBG("timeout_ms = %d\n", timeout_ms);

    while(1)
    {
        if(DRV_OK != fp_auto_enroll(dev_param, timeout_ms))
        {
            switch(fp_get_ctrlFlag(dev_param))
            {
                case FP_CONTROL_FLAG_STOPPED:
                    memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
                    snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}", 3); //录入中断
                    ofp_enroll_status_callback(id, OFP_ENROLL_STATUS_FAILED, msg_info);
                    break;
                case FP_CONTROL_FLAG_TIMEOUT:
                    memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
                    snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}", 3); //录入中断，是否有超时状态？
                    ofp_enroll_status_callback(id, OFP_ENROLL_STATUS_FAILED, msg_info);
                    //ofp_set_ops_abs_result (dev, OPS_ENROLL_TIMEOUT);          // 设置操作结果：录入超时
                    //ofp_set_notify_abs_mid (dev, NOTIFY_ENROLL_TIMEOUT);
                    break;
                case FP_CONTROL_FLAG_DEV_NOT_EXIST:
                    ofp_enroll_status_callback(id, OFP_ENROLL_STAGE_DISCONNECTED, "{}");//设备失联
                    //ofp_set_ops_result (dev, OPS_COMM_ERROR);                              //操作结果设置为：通用操作错误
                    //ofp_set_notify_abs_mid (dev, NOTIFY_COMM_DISABLE);                     //提示消息设置为：设备不可用
                    break;
                default:
                    memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
                    snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}\n", 1); //未知错误
                    ofp_enroll_status_callback(id, OFP_ENROLL_STATUS_FAILED, msg_info);
                    //ofp_set_ops_abs_result (dev, OPS_ENROLL_ERROR);          // 设置操作结果：录入错误
                    //ofp_set_notify_abs_mid (dev, NOTIFY_ENROLL_ERROR);       // 用户提醒消息：录入错误
                    break;
            }
            fp_cancel(dev_param);
            //fp_read_invalid_pkg(dev_param, 3);//规避取消报文错位，add by hcq, 20230314

            goto GDBUS_ENROLL_PT_END;
        }

        if(0 != fp_get_enroll_finish_flag(dev_param))
        {
            break;
        }

        uint8 enroll_time = fp_get_current_enroll_time(dev_param);
        if(0 < enroll_time)
        {
            uint8 create_feature_result = fp_get_enroll_create_feature_result(dev_param, enroll_time);
            if(PROT_RESP_OK == create_feature_result)
            {
                switch(fp_get_enroll_result(dev_param, enroll_time))
                {
                    case  PROT_RESP_OK: //录入成功
                        snprintf (priv->extra_info, EXTRA_INFO_LENGTH, "enroll times %d/6.\n", enroll_time);
                        //ofp_set_notify_abs_mid (dev, MID_EXTENDED_MESSAGE);
                        WD_DBG("%s", priv->extra_info);
                        memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
                        snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"progress\":%d}", (enroll_time + 1) * 100/(dev->sample_times + 1));//录入进度
                        //WD_DBG("%s\n", msg_info);
                        ofp_enroll_status_callback(id, OFP_ENROLL_STAGE_PASSED, msg_info);
#if 0//验证图像异常提示
                        memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
                        //snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}", 3);//两次触摸的指纹信息重复率过高
                        //snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}", 2);//图形不可用
                        snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}", 1);//接触时间过短
                        ofp_enroll_status_callback(id, OFP_ENROLL_STAGE_RETRY, msg_info);
#endif
                        break;
                    default:
                        snprintf (priv->extra_info, EXTRA_INFO_LENGTH, "Enroll failed, please press your finger again.\n");
                        //ofp_set_notify_abs_mid (dev, MID_EXTENDED_MESSAGE);
                        WD_DBG("Enroll failed, please press your finger again.\n");
                        memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
                        snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}", 7);//拿开手指重新录入
                        ofp_enroll_status_callback(id, OFP_ENROLL_STAGE_RETRY, msg_info);
                        break;
                }
            }
            else
            {
                switch(create_feature_result)
                {
                    case PROT_RESP_OK:break;//生成特征成功
                    case PROT_RESP_FPRINT_EXIST:    //指纹重复
                        snprintf (priv->extra_info, EXTRA_INFO_LENGTH, "Current fingerprint already exist, please press your finger again.\n");
                        //ofp_set_notify_abs_mid (dev, MID_EXTENDED_MESSAGE);
                        WD_DBG("Current fingerprint already exist, please press your finger again.\n");
                        //bio_print_debug ("%s\n", bio_get_notify_mid_mesg(dev));
                        memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
                        snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}", 4);//当前指纹已存在，请换其他手指
                        ofp_enroll_status_callback(id, OFP_ENROLL_STAGE_RETRY, msg_info);
                        break;
                    case PROT_RESP_POSITION_REPEATED:   //位置重复
                        snprintf (priv->extra_info, EXTRA_INFO_LENGTH, "Current fingerprint position repeated, please press your finger again.\n");
                        //ofp_set_notify_abs_mid (dev, MID_EXTENDED_MESSAGE);
                        WD_DBG("Current fingerprint position repeated, please press your finger again.\n");
                        //ofp_print_debug ("%s\n", bio_get_notify_mid_mesg(dev));
                        memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
                        snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}", 3);//两次触摸的指纹信息重复率过高
                        ofp_enroll_status_callback(id, OFP_ENROLL_STAGE_RETRY, msg_info);
                        break;
                    case PROT_RESP_FPRINT_QUALITY_BAD:  //指纹质量不佳
                        snprintf (priv->extra_info, EXTRA_INFO_LENGTH, "The quality of current fingerprint is bad, please press your finger again.\n");
                        //ofp_set_notify_abs_mid (dev, MID_EXTENDED_MESSAGE);
                        WD_DBG("The quality of current fingerprint is bad, please press your finger again.\n");
                        //bio_print_debug ("%s\n", bio_get_notify_mid_mesg(dev));
                        memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
                        snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}", 2);//图形不可用
                        ofp_enroll_status_callback(id, OFP_ENROLL_STAGE_RETRY, msg_info);
                        break;
                    case PROT_RESP_FPRINT_AREA_TOO_SMALL:   //指纹面积过小
                        snprintf (priv->extra_info, EXTRA_INFO_LENGTH, "The area of current fingerprint is too small, please press your finger again.\n");
                        //ofp_set_notify_abs_mid (dev, MID_EXTENDED_MESSAGE);
                        WD_DBG("The area of current fingerprint is too small, please press your finger again.\n");
                        //bio_print_debug ("%s\n", bio_get_notify_mid_mesg(dev));
                        memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
                        snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}", 1);//接触时间过短
                        ofp_enroll_status_callback(id, OFP_ENROLL_STAGE_RETRY, msg_info);
                        break;
                    default:
                        snprintf (priv->extra_info, EXTRA_INFO_LENGTH, "Enroll failed, please press your finger again.\n");
                        //ofp_set_notify_abs_mid (dev, MID_EXTENDED_MESSAGE);
                        WD_DBG("Enroll failed, please press your finger again.\n");
                        memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
                        snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}", 7);//拿开手指重新录入
                        ofp_enroll_status_callback(id, OFP_ENROLL_STAGE_RETRY, msg_info);
                        break;
                }

            }
        }
    }

    WD_DBG("enroll_id = %d\n", enroll_id);
    fp_cancel(dev_param);//规避读取固件报文错位问题，add by hcq, 20230607 13:30

    fprint_info xfprint_info;
    xfprint_info.enable = TRUE;
    strcpy(xfprint_info.user_id, id);
    strcpy(xfprint_info.fprint_name, finger);
    xfprint_info.fprint_id = enroll_id;
    ofp_add_fprint_info(dev, &xfprint_info);

    //ofprint_complete_enroll(skeleton, invocation);
    ofp_set_dev_status (dev, DEVS_COMM_IDLE);
    ofp_enroll_status_callback(id, OFP_ENROLL_STATUS_SUCCESS, "{}");

GDBUS_ENROLL_PT_END:
    fp_set_ctrlFlag(dev_param, FP_CONTROL_FLAG_IDLE);
    if(CONTROL_FLAG_STOPING == priv->ctrlFlag)
    {
        priv->ctrlFlag = CONTROL_FLAG_STOPPED;
    }
    usb_dev_close(usb_dev);
    ofp_set_dev_status (dev, DEVS_COMM_IDLE);
    free(p0);
    free(p1);
    free(p2);
    free(p3);
    g_slist_free(argv);
    WD_LOG("end.\n");

    DBG("gdbus_enroll_pt<========================exit\n");
}

static gboolean gdbus_handle_enroll(OfprintSkeleton* skeleton,
                                            GDBusMethodInvocation *invocation,
                                            char *id, char *finger)
{
    DBG("gdbus_handle_enroll ================>enter\n");
    WD_DBG("start, id=%s, finger=%s.\n", id, finger);

    int err = 0;
    pthread_t thr;

    GSList *argv = NULL;
    OfprintSkeleton **p0;
    GDBusMethodInvocation **p1;
    char *p2;
    char *p3;

    p0 = malloc(sizeof(void *));
    memcpy(p0, &skeleton, sizeof(void *));
    argv = g_slist_append(argv, p0);

    p1 = malloc(sizeof(void *));
    memcpy(p1, &invocation, sizeof(void *));
    argv = g_slist_append(argv, p1);

    p2 = ofp_new_string((char *)id);
    argv = g_slist_append(argv, p2);

    p3 = ofp_new_string((char *)finger);
    argv = g_slist_append(argv, p3);


    err = pthread_create(&thr, NULL, (void *)gdbus_enroll_pt, argv);

    if (err != 0) {
        WD_ERR(_("Can't create thread: %s\n"), strerror(err));
    }

    WD_DBG("end.\n");
    DBG("gdbus_handle_enroll <================exit\n");

    return TRUE;
}

void gdbus_stop_enroll_pt(GSList * argv)
{
    OfprintSkeleton **p0;
    GDBusMethodInvocation **p1;

    DBG("gdbus_stop_enroll_pt ================>enter\n");
    p0 = g_slist_nth_data(argv,0);
    p1 = g_slist_nth_data(argv,1);

    OfprintSkeleton *skeleton = (OfprintSkeleton *)*p0;
    GDBusMethodInvocation *invocation = (GDBusMethodInvocation *)*p1;
    ofp_dev *dev = dev_ofprint;
    driver_info *priv = (driver_info *)dev->dev_priv;
    FP_DEVICE_PARAM_STRUCT *dev_param = &(priv->fp_device_param);
    int timeout = 3 * 1000;
    int timeused = 0;

    WD_LOG("start.\n");

    if((dev->enable == FALSE) || (0 >= dev->dev_num))
    {
        goto GDBUS_STOP_ENROLL_PT_END;
    }

    if(ofp_get_dev_status(dev) == DEVS_COMM_IDLE)    // 如果设备为空闲状态
    {
        WD_DBG("DEVS_COMM_IDLE.\n");
        goto GDBUS_STOP_ENROLL_PT_END;
    }

    WD_DBG("continue.\n");

    // 设置状态位，用于通知用户中断
    priv->ctrlFlag = CONTROL_FLAG_STOPING;
    fp_set_ctrlFlag(dev_param, FP_CONTROL_FLAG_STOPPED);

    while ((priv->ctrlFlag != CONTROL_FLAG_STOPPED) &&
        (priv->ctrlFlag != CONTROL_FLAG_DONE) &&
        (priv->ctrlFlag != CONTROL_FLAG_IDLE) &&
        (timeused < timeout))
    {
        timeused += 10;
        usleep(10 * 1000);
    }

GDBUS_STOP_ENROLL_PT_END:
    if ((priv->ctrlFlag == CONTROL_FLAG_STOPPED)
        || (priv->ctrlFlag == CONTROL_FLAG_DONE))
    {
        priv->ctrlFlag == CONTROL_FLAG_IDLE;
    }

    ofprintx_complete_stop_enroll(skeleton, invocation);
    free(p0);
    free(p1);
    g_slist_free(argv);
    WD_LOG("end.\n");
    DBG("gdbus_stop_enroll_pt <================exit\n");
}

static gboolean gdbus_handle_stop_enroll(OfprintSkeleton* skeleton,
                                            GDBusMethodInvocation *invocation)
{
    DBG("gdbus_handle_stop_enroll=================>enter\n");
    WD_DBG("start.\n");

    int err = 0;
    pthread_t thr;

    GSList *argv = NULL;
    OfprintSkeleton **p0;
    GDBusMethodInvocation **p1;

    p0 = malloc(sizeof(void *));
    memcpy(p0, &skeleton, sizeof(void *));
    argv = g_slist_append(argv, p0);

    p1 = malloc(sizeof(void *));
    memcpy(p1, &invocation, sizeof(void *));
    argv = g_slist_append(argv, p1);

    err = pthread_create(&thr, NULL, (void *)gdbus_stop_enroll_pt, argv);

    if (err != 0) {
        WD_ERR(_("Can't create thread: %s\n"), strerror(err));
    }

    WD_DBG("end.\n");
    DBG("gdbus_handle_stop_enroll=================>exit\n");

    //return FALSE;
    return TRUE;
}

/*
 * 初始化过程中先发起identify获取一键开机结果，并保存15秒钟
*/
int ofp_onekey_powerup_identify(ofp_dev *dev)
{
    driver_info *priv = (driver_info *)dev->dev_priv;
    FP_DEVICE_PARAM_STRUCT *dev_param = &(priv->fp_device_param);
    USB_DEV_STRUCT *usb_dev = &(dev_param->usb_dev);
    INTF_USB_ID_STRUCT *id_table = (INTF_USB_ID_STRUCT *)(dev->usb_info.id_table);

    WD_DBG("start.\n");

    if((NULL == usb_get_dev_handle(usb_dev)) && (DRV_OK != usb_dev_open(usb_dev, id_table)))
    {
        WD_DBG("can't open device!!!\n");
        return -1;
    }

    init_onekey_powerup_search_id(dev_param);
    fp_onekey_powerup_identify(dev_param, 3, 0xffff, FP_CURRENT_OS_TYPE, get_onekey_powerup_search_id(dev_param), 20);
    fp_cancel(dev_param);

    if(1 != get_onekey_powerup_flag(dev_param))
    {
        set_onekey_powerup_flag(dev_param, 0);//若未读取到一键开机结果则设置为0
    }

    usb_dev_close(usb_dev);

    return DRV_OK;
}


void gdbus_verify_pt(GSList * argv)
{
    OfprintSkeleton **p0;
    GDBusMethodInvocation **p1;
    char *p2;

    p0 = g_slist_nth_data(argv,0);
    p1 = g_slist_nth_data(argv,1);
    p2 = g_slist_nth_data(argv,2);
    DBG("gdbus_verify_pt==============>enter\n");
    OfprintSkeleton *skeleton = (OfprintSkeleton *)*p0;
    GDBusMethodInvocation *invocation = (GDBusMethodInvocation *)*p1;
    char *finger = p2;
    ofp_dev *dev = dev_ofprint;
    driver_info *priv = (driver_info *)dev->dev_priv;
    FP_DEVICE_PARAM_STRUCT *dev_param = &(priv->fp_device_param);
    USB_DEV_STRUCT *usb_dev = &(dev_param->usb_dev);
    INTF_USB_ID_STRUCT *id_table = (INTF_USB_ID_STRUCT *)(dev->usb_info.id_table);

    char msg_info[OFP_MSG_SIZE_MAX] = {0};
    uint16 identify_id = 0xffff;
    //uint16 identify_result_id = 0xffff;
    uint16 identify_result_id[ENROLL_NUM_MAX];
    int verifytimes = 0;
    int found_result = -1;//是否搜索到当前帐户指纹标志
    struct timeval tv_begin;
    struct timeval tv_end;
    int verify_time_ms = 0;
    fprint_info *fprint_found = NULL;
    static uint32 entry_count = 0;
    entry_count++;

    WD_DBG("start, entry_count = %d, finger=%s.\n", entry_count, finger);

    ofprintx_complete_verify(skeleton, invocation);
    if((dev->enable == FALSE) || ((0 >= dev->dev_num) && (0 == get_onekey_powerup_flag(dev_param))))
    {
        //ofp_verify_status_callback("", OFP_VERIFY_STAGE_DISCONNECTED, "{}");//与设备失联
        ofp_verify_status_callback(priv->user_id, OFP_VERIFY_STAGE_DISCONNECTED, NULL);//与设备失联
        goto GDBUS_VERIFY_PT_END;
    }

    if(DEVS_COMM_IDLE != ofp_get_dev_status(dev))//设备非空闲状态
    {
        memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
        snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}\n", 1); //未知错误
        //ofp_verify_status_callback("", OFP_VERIFY_STAGE_ERROR, msg_info);
        ofp_verify_status_callback(priv->user_id, OFP_VERIFY_STAGE_ERROR, msg_info);
        WD_DBG("ofp_get_dev_status(dev) = %d, not IDLE!\n", ofp_get_dev_status(dev));
        goto GDBUS_VERIFY_PT_END;
    }

#if 0//识别过程中似乎会出现usb断开问题，故每次识别均重新打开usb
    if((NULL == usb_get_dev_handle(usb_dev)) && (DRV_OK != usb_dev_open(usb_dev, id_table)))
    {
        //ofp_verify_status_callback("", OFP_VERIFY_STAGE_DISCONNECTED, "{}");//与设备失联
        ofp_verify_status_callback(priv->user_id, OFP_VERIFY_STAGE_DISCONNECTED, NULL);//与设备失联
        WD_DBG("open device failed!\n");
        goto GDBUS_VERIFY_PT_END;
    }
#endif

    ofp_set_dev_status (dev, DEVS_VERIFY_DOING);         // 设备状态：正在验证
    gettimeofday(&tv_begin, NULL);

    memset((char *)identify_result_id, 0xff, sizeof(identify_result_id));
    //fp_read_invalid_pkg(dev_param, 5);//规避读取固件报文错位问题，add by hcq, 20230607 13:30，取消读空，避免睡眠时读不到一键开机结果
    //usleep(500 * 1000);//uos验证一键开机启动时验证通过，但未进入系统桌面，测试延时能进入

    //此处用于规避模组一键开机时，会将结果直接缓存在usb队列中，导致驱动初始化读取模组固件版本时，
    //先读到一键开机的结果，应答报文错位，流程混乱，后续应当由模组修改保证指令应答的准确性，add by hcq, 20230607
    if((1 == get_onekey_powerup_flag(dev_param))&&(40*1000 > fp_get_increment_of_time_ms(get_onekey_powerup_tv_time(dev_param))))
    {

        WD_LOG("received one key power up identify result.\n");
        //memcpy(identify_result_id, get_onekey_powerup_search_id(), get_onekey_powerup_search_num());
        for(int count = 0; count < get_onekey_powerup_search_num(dev_param); count++)
        {
            identify_result_id[count] = get_onekey_powerup_search_id(dev_param)[count];
        }
        set_onekey_powerup_flag(dev_param, 0);
        //WD_DBG("sleep 700ms\n");
        //usleep(700 * 1000);
        if(1 == get_onekey_restart_flag(dev_param))
        {
            set_onekey_restart_flag(dev_param, 0);
            //WD_DBG("sleep 1s\n");
            //sleep(1);
            int change_ms_value = get_restart_tv_begin_change_ms(dev_param);
            //int delay_ms_value = 2000;//延时2000ms
            //int delay_ms_value = 1000;//延时1000ms
            int delay_ms_value = 0;//not delay
            if((0 < change_ms_value) && (change_ms_value < delay_ms_value))
            {
                usleep((delay_ms_value - change_ms_value) * 1000);
                WD_DBG("sleep %d ms\n", delay_ms_value - change_ms_value);
            }
            //usleep(200 * 1000);
            //WD_DBG("not delay.\n");
        }
        else
        {
            WD_DBG("sleep 2s\n");
            sleep(2);
        }
        goto GDBUS_VERIFY_PT_DEAL_WITH_RESULT_ID;//若为一键开机结果，则直接跳转到处理结果
    }
    set_onekey_powerup_flag(dev_param, 0);
    set_onekey_restart_flag(dev_param, 0);

#if 1//识别过程中似乎会出现usb断开问题，故每次识别均重新打开usb
        if((NULL == usb_get_dev_handle(usb_dev)) && (DRV_OK != usb_dev_open(usb_dev, id_table)))
        {
            //ofp_verify_status_callback("", OFP_VERIFY_STAGE_DISCONNECTED, "{}");//与设备失联
            ofp_verify_status_callback(priv->user_id, OFP_VERIFY_STAGE_DISCONNECTED, NULL);//与设备失联
            WD_DBG("open device failed!\n");
            goto GDBUS_VERIFY_PT_END;
        }
#endif


    //gettimeofday(&tv_begin, NULL);

#ifdef OFP_VERIFY_TIMES_MAX //ofprint-server.h若定义了限制验证次数，则超过次数后无法进行指纹验证
    for(verifytimes = 0; verifytimes < OFP_VERIFY_TIMES_MAX; verifytimes++)
#else
    //while(1)//是否需要限制验证次数
    for(verifytimes = 0; verifytimes < 1; verifytimes++)
#endif
    {
        if(CONTROL_FLAG_STOPING == priv->ctrlFlag)
        {
            WD_DBG("received CONTROL_FLAG_STOPING\n");
            goto GDBUS_VERIFY_PT_END;
        }
#if 0
        if((NULL == usb_get_dev_handle(usb_dev)) && (DRV_OK != usb_dev_open(usb_dev, id_table)))//当识别到错误指纹时，usb会断开，此处规避，add by hcq, 20230323
        {
            //ofp_verify_status_callback("", OFP_VERIFY_STAGE_DISCONNECTED, "{}");//与设备失联
            ofp_verify_status_callback(NULL, OFP_VERIFY_STAGE_DISCONNECTED, NULL);//与设备失联
            if(CONTROL_FLAG_STOPING == priv->ctrlFlag)
            {
                //ofp_verify_status_callback("", OFP_VERIFY_STATUS_NOMATCH, "{}");  //用户取消，返回不匹配
                ofp_verify_status_callback(NULL, OFP_VERIFY_STATUS_NOMATCH, NULL);  //用户取消，返回不匹配
                goto GDBUS_VERIFY_PT_END;
            }
            continue;
            //goto GDBUS_VERIFY_PT_END;
        }
#endif
        //identify_result_id = 0xffff;
        memset((char *)identify_result_id, 0xff, sizeof(identify_result_id));
        found_result = -1;

        if(DRV_OK != fp_auto_identify(dev_param, 3, identify_id, FP_CURRENT_OS_TYPE, identify_result_id, 0))
        //if(DRV_OK != fp_auto_identify(3, identify_id, FP_ALL_OS_TYPE, &identify_result_id, 0))
        //if(DRV_OK != fp_auto_identify(3, identify_id, FP_WINDOWS_OS_TYPE, &identify_result_id, 0))
        //if(DRV_OK != fp_auto_identify(3, identify_id, FP_KYLIN_OS_TYPE, &identify_result_id, 0))
        //if(DRV_OK != fp_auto_identify(3, identify_id, FP_UOS_OS_TYPE, &identify_result_id, 0))
        {
            switch(fp_get_ctrlFlag(dev_param))
            {
                case FP_CONTROL_FLAG_STOPPED:
                    //ofp_set_ops_result (dev, OPS_COMM_STOP_BY_USER);
                    //ofp_set_notify_mid (dev, NOTIFY_COMM_STOP_BY_USER);
                    WD_DBG("FP_CONTROL_FLAG_STOPPED\n");
                    break;
                case FP_CONTROL_FLAG_TIMEOUT:
                    //fp_cancel(dev_param);
                    //ofp_set_ops_abs_result (dev, OPS_VERIFY_TIMEOUT);          // 设置操作结果：验证超时
                    //ofp_set_notify_abs_mid (dev, NOTIFY_VERIFY_TIMEOUT);
                    WD_DBG("FP_CONTROL_FLAG_TIMEOUT\n");
                    break;
                case FP_CONTROL_FLAG_DEV_NOT_EXIST:
                    //ofp_verify_status_callback("", OFP_VERIFY_STAGE_DISCONNECTED, "{}");//与设备失联
                    ofp_verify_status_callback(priv->user_id, OFP_VERIFY_STAGE_DISCONNECTED, NULL);//与设备失联
                    WD_DBG("FP_CONTROL_FLAG_DEV_NOT_EXIST\n");
                    //goto GDBUS_VERIFY_PT_END;//当识别到错误指纹时，usb会断开，此处规避，add by hcq, 20230323
                    break;
                default:
                    //fp_cancel(dev_param);
                    //ofp_set_ops_abs_result (dev, OPS_VERIFY_ERROR);          // 设置操作结果：验证错误
                    //ofp_set_notify_abs_mid (dev, NOTIFY_VERIFY_ERROR);       // 用户提醒消息：验证错误
                    WD_DBG("OPS_VERIFY_ERROR\n");
                    break;
            }

            fp_cancel(dev_param);
            //fp_read_invalid_pkg(dev_param, 3);//规避取消报文错位，add by hcq, 20230314
            fp_set_ctrlFlag(dev_param, FP_CONTROL_FLAG_IDLE);
            if(CONTROL_FLAG_STOPING == priv->ctrlFlag)
            {
                //ofp_verify_status_callback("", OFP_VERIFY_STATUS_NOMATCH, "{}");  //用户取消，返回不匹配
                //ofp_verify_status_callback(NULL, OFP_VERIFY_STATUS_NOMATCH, NULL);    //用户取消，返回不匹配
                //ofp_verify_status_callback(priv->user_id, OFP_VERIFY_STATUS_NOMATCH, NULL);   //用户取消，返回不匹配
                goto GDBUS_VERIFY_PT_END;
            }

            //memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
            //ofp_verify_status_callback(NULL, OFP_VERIFY_STATUS_NOMATCH, msg_info);
            //ofprint_complete_verify(skeleton, invocation);
            memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
            snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}", OFP_VERIFY_REMOVE_AND_RETRY);
            ofp_verify_status_callback(priv->user_id, OFP_VERIFY_STAGE_RETRY, msg_info);
            //ofp_verify_status_callback(NULL, OFP_VERIFY_STAGE_RETRY, msg_info);
            //usb_dev_close(usb_dev);//当识别到错误指纹时，usb会断开，此处规避，add by hcq, 20230323
            continue;
        }
#if 0
        if(0xffff == identify_result_id[0])
        {
            memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
            snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}", OFP_VERIFY_REMOVE_AND_RETRY);
            //ofp_verify_status_callback("", OFP_VERIFY_STAGE_RETRY, msg_info);
            ofp_verify_status_callback(NULL, OFP_VERIFY_STAGE_RETRY, msg_info);
            //ofprint_complete_verify(skeleton, invocation);
            //ofp_set_dev_status (dev, DEVS_COMM_IDLE);
            //return TRUE;
            continue;
        }

        WD_DBG("identify_result_id[0] = %d\n", identify_result_id[0]);
#endif

GDBUS_VERIFY_PT_DEAL_WITH_RESULT_ID:


        for(int n = 0; n < ENROLL_NUM_MAX; n++)
        {
            if(0xffff == identify_result_id[n])
            {
                memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
                snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}", OFP_VERIFY_REMOVE_AND_RETRY);
                //snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}", OFP_VERIFY_SWIPE_TOO_SHORT);
                //ofp_verify_status_callback(NULL, OFP_VERIFY_STAGE_RETRY, msg_info);
#if 0
                ofp_verify_status_callback(priv->user_id, OFP_VERIFY_STAGE_RETRY, msg_info);
#else
                //ofp_verify_status_callback(priv->user_id, OFP_VERIFY_STATUS_NOMATCH, NULL);   //返回不匹配
#endif
                break;
            }

            ofp_find_fprint_info_byfprintid(dev, identify_result_id[n], &fprint_found);

            //if(NULL != fprint_found)
            if((NULL != fprint_found) && (0 == strcmp(priv->user_id, fprint_found->user_id)))//增加判断是否为当前帐户
            {
                memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
                WD_DBG("user_id = %s\n", fprint_found->user_id);
                //ofp_verify_status_callback(fprint_found->user_id, OFP_VERIFY_STATUS_MATCH, msg_info);
                found_result = 0;
#if 0
                ofp_verify_status_callback(fprint_found->user_id, OFP_VERIFY_STATUS_MATCH, NULL);
#else //uos验证一键开机启动时验证通过，但未进入系统桌面，测试多发送几次是否能进入
                gettimeofday(&tv_end, NULL);

                if(tv_end.tv_usec > tv_begin.tv_usec)
                {
                    verify_time_ms = (tv_end.tv_sec - tv_begin.tv_sec)*1000 +\
                        (tv_end.tv_usec - tv_begin.tv_usec)/1000;
                }
                else
                {
                    verify_time_ms = (tv_end.tv_sec - tv_begin.tv_sec - 1)*1000 +\
                        (tv_end.tv_usec + 1000*1000 - tv_begin.tv_usec)/1000;
                }

                D_DBG("verify_time_ms = %d\n", verify_time_ms);

                if(80 > verify_time_ms)//测试50ms内完成一键开机指纹搜索结果读取，增加到80ms降低风险
                {
                    //usleep(700 * 1000);//休眠700ms
                    //sleep(2);//休眠2秒
                    usleep(200 * 1000);//休眠200ms
                }

                if(CONTROL_FLAG_STOPING == priv->ctrlFlag)
                {
                    fp_onekey_restart_identify_2(dev_param, identify_result_id);
                    goto GDBUS_VERIFY_PT_END;
                }

                //有时发送验证结果系统未处理，一直等待，导致按压指纹无反应，需切换密码解锁再切回来，此处修改规避，by hcq, 20240522
                for(int retry_count = 0; retry_count <= 3 * 100; retry_count++)
                {
                    if (0 == retry_count % 100)
                    {
                        ofp_verify_status_callback(fprint_found->user_id, OFP_VERIFY_STATUS_MATCH, NULL);
                    }

                    usleep(10 * 1000);
                    if(CONTROL_FLAG_STOPING == priv->ctrlFlag)
                        break;
                }
#endif
                goto GDBUS_VERIFY_PT_END;
                //usleep(10 * 1000);
                //break;//由uos生物识别代理调用stop verify结束
            }
#if 0
            else
            {
                WD_DBG("user_id = NULL\n");
                ofp_verify_status_callback(priv->user_id, OFP_VERIFY_STATUS_NOMATCH, NULL); //返回不匹配
            }
#endif
            //usleep(10 * 1000);

            if(FP_CONTROL_FLAG_STOPPED == fp_get_ctrlFlag(dev_param))
            {
                WD_DBG("received CONTROL_FLAG_STOPING\n");
                if(NULL != usb_get_dev_handle(usb_dev))
                {
                    fp_cancel(dev_param);
                }
                //fp_read_invalid_pkg(dev_param, 3);//规避取消报文错位，add by hcq, 20230314
                goto GDBUS_VERIFY_PT_END;
            }
        }

        if(0 != found_result)
        {
            WD_DBG("user_id = NULL\n");
            if(CONTROL_FLAG_STOPING == priv->ctrlFlag)
            {
                fp_onekey_restart_identify_2(dev_param, identify_result_id);
                goto GDBUS_VERIFY_PT_END;
            }

            //有时发送验证结果系统未处理，一直等待，导致按压指纹无反应，需切换密码解锁再切回来，此处修改规避，by hcq, 20240522
            for(int retry_count = 0; retry_count <= 3 * 100; retry_count++)
            {
                if (0 == retry_count % 100)
                {
                    ofp_verify_status_callback(priv->user_id, OFP_VERIFY_STATUS_NOMATCH, NULL); //返回不匹配
                }
                usleep(10 * 1000);

                if(CONTROL_FLAG_STOPING == priv->ctrlFlag)
                    goto GDBUS_VERIFY_PT_END;
            }
            //goto GDBUS_VERIFY_PT_END;
        }

        usleep(200 * 1000);//休眠100ms，若收到取消指令则返回
        //usb_dev_close(usb_dev);//当识别到错误指纹时，usb会断开，此处规避，add by hcq, 20230323
    }
    if(NULL != usb_get_dev_handle(usb_dev))
    {
        fp_cancel(dev_param);
    }

#ifdef OFP_VERIFY_TIMES_MAX
    if(OFP_VERIFY_TIMES_MAX == verifytimes)
    {
        //ofp_verify_status_callback("", OFP_VERIFY_STATUS_NOMATCH, "{}");
        ofp_verify_status_callback(priv->user_id, OFP_VERIFY_STATUS_NOMATCH, NULL);
    }
#endif

GDBUS_VERIFY_PT_END:
    //ofprint_complete_verify(skeleton, invocation);//此处会导致验证流程无法结束
    fp_set_ctrlFlag(dev_param, FP_CONTROL_FLAG_IDLE);
    if(CONTROL_FLAG_STOPING == priv->ctrlFlag)
    {
        priv->ctrlFlag = CONTROL_FLAG_STOPPED;
    }
    usb_dev_close(usb_dev);
    ofp_set_dev_status (dev, DEVS_COMM_IDLE);
    free(p0);
    free(p1);
    free(p2);
    g_slist_free(argv);
    WD_LOG("end.\n");
    DBG("gdbus_verify_pt<==============exit\n");

}




static gboolean gdbus_handle_verify(OfprintSkeleton* skeleton,
                                            GDBusMethodInvocation *invocation,
                                            char *finger)
{
    DBG("gdbus_handle_verify =======================>enter\n");
    WD_DBG("start, finger=%s.\n", finger);

    int err = 0;
    pthread_t thr;

    GSList *argv = NULL;
    OfprintSkeleton **p0;
    GDBusMethodInvocation **p1;
    char *p2;

    p0 = malloc(sizeof(void *));
    memcpy(p0, &skeleton, sizeof(void *));
    argv = g_slist_append(argv, p0);

    p1 = malloc(sizeof(void *));
    memcpy(p1, &invocation, sizeof(void *));
    argv = g_slist_append(argv, p1);

    p2 = ofp_new_string((char *)finger);
    argv = g_slist_append(argv, p2);

    err = pthread_create(&thr, NULL, (void *)gdbus_verify_pt, argv);

    if (err != 0) {
        WD_ERR(_("Can't create thread: %s\n"), strerror(err));
    }
    DBG("gdbus_handle_verify <=======================exit\n");

    return TRUE;
}

void gdbus_stop_verify_pt(GSList * argv)
{
    OfprintSkeleton **p0;
    GDBusMethodInvocation **p1;

    p0 = g_slist_nth_data(argv,0);
    p1 = g_slist_nth_data(argv,1);

    OfprintSkeleton *skeleton = (OfprintSkeleton *)*p0;
    GDBusMethodInvocation *invocation = (GDBusMethodInvocation *)*p1;
    ofp_dev *dev = dev_ofprint;
    driver_info *priv = (driver_info *)dev->dev_priv;
    FP_DEVICE_PARAM_STRUCT *dev_param = &(priv->fp_device_param);
    int timeout = 3 * 1000;//3s 超时
    int timeused = 0;

    WD_LOG("start.\n");

    if((dev->enable == FALSE) || (0 >= dev->dev_num))
    {
        goto GDBUS_STOP_VERIFY_PT_END;
    }

    if(ofp_get_dev_status(dev) == DEVS_COMM_IDLE)    // 如果设备为空闲状态
    {
        WD_DBG("DEVS_COMM_IDLE.\n");
        goto GDBUS_STOP_VERIFY_PT_END;
    }

    WD_DBG("continue.\n");

    // 设置状态位，用于通知用户中断
    priv->ctrlFlag = CONTROL_FLAG_STOPING;
    fp_set_ctrlFlag(dev_param, FP_CONTROL_FLAG_STOPPED);

    while ((priv->ctrlFlag != CONTROL_FLAG_STOPPED) &&
        (priv->ctrlFlag != CONTROL_FLAG_DONE) &&
        (priv->ctrlFlag != CONTROL_FLAG_IDLE) &&
        (timeused < timeout) &&
        (ofp_get_dev_status(dev) != DEVS_COMM_IDLE))
    {
        timeused += 10;//EM1600DEV_FINGER_CHECK_INTERVAL_MS;
        usleep(10 * 1000);//usleep(EM1600DEV_FINGER_CHECK_INTERVAL_MS * 1000);
    }

GDBUS_STOP_VERIFY_PT_END:
    if ((priv->ctrlFlag == CONTROL_FLAG_STOPPED)
        || (priv->ctrlFlag == CONTROL_FLAG_DONE)
        || (ofp_get_dev_status(dev) == DEVS_COMM_IDLE))
    {
        priv->ctrlFlag == CONTROL_FLAG_IDLE;
    }

    ofprintx_complete_stop_verify(skeleton, invocation);
    free(p0);
    free(p1);
    g_slist_free(argv);
    WD_LOG("end.\n");
}

static gboolean gdbus_handle_stop_verify(OfprintSkeleton* skeleton,
                                            GDBusMethodInvocation *invocation)
{
    DBG("gdbus_handle_stop_verify ==============>enter\n");
    WD_DBG("start.\r\n");

    int err = 0;
    pthread_t thr;

    GSList *argv = NULL;
    OfprintSkeleton **p0;
    GDBusMethodInvocation **p1;

    p0 = malloc(sizeof(void *));
    memcpy(p0, &skeleton, sizeof(void *));
    argv = g_slist_append(argv, p0);

    p1 = malloc(sizeof(void *));
    memcpy(p1, &invocation, sizeof(void *));
    argv = g_slist_append(argv, p1);

    err = pthread_create(&thr, NULL, (void *)gdbus_stop_verify_pt, argv);

    if (err != 0) {
        WD_ERR(_("Can't create thread: %s\n"), strerror(err));
    }
    DBG("gdbus_handle_stop_verify <==============exit\n");

    return TRUE;
}

static gboolean gdbus_handle_delete_finger(OfprintSkeleton* skeleton,
                                            GDBusMethodInvocation *invocation,
                                            char *id, char *finger)
{
    DBG("gdbus_handle_delete_finger=================>enter\n");
    WD_DBG("start, id=%s, finger=%s.\n", id, finger);

    ofp_dev *dev = dev_ofprint;
    driver_info *priv = (driver_info *)dev->dev_priv;
    FP_DEVICE_PARAM_STRUCT *dev_param = &(priv->fp_device_param);
    USB_DEV_STRUCT *usb_dev = &(dev_param->usb_dev);
    INTF_USB_ID_STRUCT *id_table = (INTF_USB_ID_STRUCT *)(dev->usb_info.id_table);

    fprint_info *fprint_found = NULL;
    uint16 enroll_id = 0xffff;
    int ret = 0;
    int index = 0;

    if((dev->enable == FALSE) || (0 >= dev->dev_num))// 设备不可用
    {
        WD_LOG("device disable!!!\n");
        goto GDBUS_HANDLE_DELETE_FINGER_END;
    }

    if(DEVS_COMM_IDLE != ofp_get_dev_status(dev))//设备非空闲状态
    {
        WD_LOG("device not idle!!!\n");
        goto GDBUS_HANDLE_DELETE_FINGER_END;
    }

    if((NULL == usb_get_dev_handle(usb_dev)) && (DRV_OK != usb_dev_open(usb_dev, id_table)))
    {
        WD_LOG("open device failed!!!\n");
        goto GDBUS_HANDLE_DELETE_FINGER_END;
    }

    ofp_set_dev_status (dev, DEVS_CLEAN_DOING);       //设备状态设置为：正在清理特征数据
    index = ofp_find_fprint_info(dev, id, finger, &fprint_found);
    if(NULL == fprint_found)
    {
        WD_LOG("not find id=%s finger=%s!!!\n", id, finger);
        goto GDBUS_HANDLE_DELETE_FINGER_END;
    }

    enroll_id = fprint_found->fprint_id;
    WD_DBG("enroll_id = %d\n", enroll_id);
    ret = fp_delete_template(dev_param, enroll_id, 1);
    if (ret == 0)
    {
        ofp_del_fprint_info(dev, id, finger);
    }
    else
    {
        WD_LOG("fp_delete_template enroll_id=%d failed!!!\n", enroll_id);
    }

#if 0
    if(0 != ofp_delete_invalid_feature(dev))
    {
        WD_ERR("ofp_delete_invalid_feature failed!!!\n");
    }
#endif

GDBUS_HANDLE_DELETE_FINGER_END:
    usb_dev_close(usb_dev);
    ofp_set_dev_status (dev, DEVS_COMM_IDLE);
    ofprintx_complete_delete_finger(skeleton, invocation);
    WD_DBG("end.\n");
    DBG("gdbus_handle_delete_finger=================>exit\n");

    return TRUE;
}

static gboolean gdbus_handle_delete_all_fingers(OfprintSkeleton* skeleton,
                                            GDBusMethodInvocation *invocation,
                                            char *id)
{
    DBG("gdbus_handle_delete_all_fingers======================>enter\n");
    WD_DBG("start, id=%s.\n", id);

    ofp_dev *dev = dev_ofprint;
    driver_info *priv = (driver_info *)dev->dev_priv;
    FP_DEVICE_PARAM_STRUCT *dev_param = &(priv->fp_device_param);
    USB_DEV_STRUCT *usb_dev = &(dev_param->usb_dev);
    INTF_USB_ID_STRUCT *id_table = (INTF_USB_ID_STRUCT *)(dev->usb_info.id_table);

    fprint_info *fprint_list = priv->fprint_list;

    if((dev->enable == FALSE) || (0 >= dev->dev_num))// 设备不可用
    {
        WD_LOG("device disable!!!\n");
        goto GDBUS_HANDLE_DELETE_ALL_FINGERS_END;
    }

    if(DEVS_COMM_IDLE != ofp_get_dev_status(dev))//设备非空闲状态
    {
        WD_LOG("device not idle!!!\n");
        goto GDBUS_HANDLE_DELETE_ALL_FINGERS_END;
    }

    if((NULL == usb_get_dev_handle(usb_dev)) && (DRV_OK != usb_dev_open(usb_dev, id_table)))
    {
        WD_LOG("open device failed!!!\n");
        goto GDBUS_HANDLE_DELETE_ALL_FINGERS_END;
    }

    ofp_set_dev_status (dev, DEVS_CLEAN_DOING);       //设备状态设置为：正在清理特征数据

    for(int i = 0; i < OFP_FPRINT_NUM_MAX; i++)
    {
        if((TRUE == fprint_list[i].enable)\
            &&(0 == strcmp(id, fprint_list[i].user_id)))
        {
            uint16 enroll_id = fprint_list[i].fprint_id;
            int ret = 0;
            ret = fp_delete_template(dev_param, enroll_id, 1);
            if(DRV_OK != ret)
            {
                WD_ERR("fp_delete_template enroll_id %d failed!!!\n", enroll_id);
            }
            else
            {
                ofp_del_fprint_info(dev, fprint_list[i].user_id, fprint_list[i].fprint_name);
            }
        }
    }

#if 0
    if(0 != ofp_delete_invalid_feature(dev))
    {
        WD_ERR("ofp_delete_invalid_feature failed!!!\n");
    }
#endif

GDBUS_HANDLE_DELETE_ALL_FINGERS_END:
    usb_dev_close(usb_dev);
    ofp_set_dev_status (dev, DEVS_COMM_IDLE);
    ofprintx_complete_delete_all_fingers(skeleton, invocation);
    WD_DBG("end.\n");
    DBG("gdbus_handle_delete_all_fingers<======================exit\n");

    return TRUE;
}

static gboolean gdbus_handle_list_fingers(OfprintSkeleton* skeleton,
                                            GDBusMethodInvocation *invocation,
                                            char *id)
{
    DBG("gdbus_handle_list_fingers=====================>enter\n");
    WD_DBG("start, id=%s.\n", id);

    ofp_dev *dev = dev_ofprint;
    driver_info *priv = (driver_info *)dev->dev_priv;
    FP_DEVICE_PARAM_STRUCT *dev_param = &(priv->fp_device_param);
    fprint_info *fprint_list = priv->fprint_list;
    int i = 0;
    int count = 0;

    finger_name = (char **)g_new0(char*, OFP_FPRINT_NUM_MAX);//二维数组

    if(0 >= dev->dev_num)
    {
        set_onekey_powerup_flag(dev_param, 0);
        set_onekey_restart_flag(dev_param, 0);
        WD_LOG("can't open device.\n");

        DBG("gdbus_handle_list_fingers<=====================error 1 exit\n");
        ofprintx_complete_list_fingers(skeleton, invocation, (const gchar *const *)finger_name);
        return TRUE;
    }

    if(0 != ofp_get_fprint_list(dev))
    {
        ofprintx_complete_list_fingers(skeleton, invocation, (const gchar *const *)finger_name);

        DBG("gdbus_handle_list_fingers<=====================error 2 exit\n");
        return TRUE;
    }

    for(i = 0; i < OFP_FPRINT_NUM_MAX; i++)
    {
        if((TRUE == fprint_list[i].enable)\
            && (0 == strcmp(id, fprint_list[i].user_id)))
        {
            char *tmp = (char *)g_new0(char, OFP_FPRINT_NAME_LEN_MAX);
            strncpy(tmp, fprint_list[i].fprint_name, OFP_FPRINT_NAME_LEN_MAX);
            finger_name[count++] = tmp;
            WD_DBG("%s\n", finger_name[count-1]);
        }
    }
    ofprintx_complete_list_fingers(skeleton, invocation, (const gchar *const *)finger_name);

    for(i = 0; i < count; i++)
    {
        g_free(finger_name[i]);
    }
    g_free(finger_name);
    finger_name = NULL;

    WD_DBG("end.\n");
    DBG("gdbus_handle_list_fingers<=====================exit\n");

    return TRUE;
}

static gboolean gdbus_handle_rename_finger(OfprintSkeleton* skeleton,
                                            GDBusMethodInvocation *invocation,
                                            char *id, char *finger, char *newName)
{
    DBG("gdbus_handle_rename_finger ======================>enter\n");
    WD_DBG("start, id=%s, finger=%s, newName=%s.\n", id, finger, newName);

    ofp_dev *dev = dev_ofprint;
    fprint_info *fprint_found = NULL;
    int index = 0;

    //ofp_set_dev_status (dev, DEVS_RENAME_DOING);       //设备状态设置为：正在清理特征数
    index = ofp_find_fprint_info(dev, id, finger, &fprint_found);
    if(NULL == fprint_found)
    {
        WD_ERR("ofp_find_fprint_info not found!!!\n");
    }
    else
    {
        if(0 < strlen(newName))
        {
            strcpy(fprint_found->fprint_name, newName);
            if(0 != ofp_set_fprint_info(dev, index, fprint_found))
            {
                WD_ERR("ofp_set_fprint_info failed!!!\n");
            }
        }
    }
    ofprintx_complete_rename_finger(skeleton, invocation);
    WD_DBG("end.\n");

    DBG("gdbus_handle_rename_finger <======================exit\n");
    return TRUE;
}

void gdbus_identify_with_multiple_user_pt(GSList * argv)
{
    OfprintSkeleton **p0;
    GDBusMethodInvocation **p1;

    p0 = g_slist_nth_data(argv,0);
    p1 = g_slist_nth_data(argv,1);
    DBG("gdbus_identify_with_multiple_user_pt=======================>enter\n");
    OfprintSkeleton *skeleton = (OfprintSkeleton *)*p0;
    GDBusMethodInvocation *invocation = (GDBusMethodInvocation *)*p1;

    ofp_dev *dev = dev_ofprint;
    driver_info *priv = (driver_info *)dev->dev_priv;
    FP_DEVICE_PARAM_STRUCT *dev_param = &(priv->fp_device_param);
    USB_DEV_STRUCT *usb_dev = &(dev_param->usb_dev);
    INTF_USB_ID_STRUCT *id_table = (INTF_USB_ID_STRUCT *)(dev->usb_info.id_table);

    char msg_info[OFP_MSG_SIZE_MAX] = {0};
    uint16 identify_id = 0xffff;
    uint16 identify_result_id[ENROLL_NUM_MAX];
    int verifytimes = 0;
    int found_result = -1;//是否搜索到当前帐户指纹标志
    struct timeval tv_begin;
    struct timeval tv_end;
    int verify_time_ms = 0;
    fprint_info *fprint_found = NULL;

    WD_DBG("start.\n");

    ofprintx_complete_identify_with_multiple_user(skeleton, invocation);
    if((dev->enable == FALSE) || (0 >= dev->dev_num))
    {
        ofp_identify_with_multiple_user_status_callback(NULL);//与设备失联
        goto GDBUS_IDENTIFY_WITH_MULTIPLE_USER_PT_END;
    }

    if(DEVS_COMM_IDLE != ofp_get_dev_status(dev))//设备非空闲状态
    {
        ofp_identify_with_multiple_user_status_callback(NULL);
        goto GDBUS_IDENTIFY_WITH_MULTIPLE_USER_PT_END;
    }

#if 1//识别过程中似乎会出现usb断开问题，故每次识别均重新打开usb
    if((NULL == usb_get_dev_handle(usb_dev)) && (DRV_OK != usb_dev_open(usb_dev, id_table)))
    {
        ofp_identify_with_multiple_user_status_callback(NULL);//与设备失联
        goto GDBUS_IDENTIFY_WITH_MULTIPLE_USER_PT_END;
    }
#endif

    ofp_set_dev_status (dev, DEVS_VERIFY_DOING);         // 设备状态：正在验证
    memset((char *)identify_result_id, 0xff, sizeof(identify_result_id));
    //fp_read_invalid_pkg(dev_param, 5);//规避读取固件报文错位问题，add by hcq, 20230607 13:30 取消读空，避免睡眠时一键开机读取不到结果
    //usleep(500 * 1000);//uos验证一键开机启动时验证通过，但未进入系统桌面，测试延时能进入

    //此处用于规避模组一键开机时，会将结果直接缓存在usb队列中，导致驱动初始化读取模组固件版本时，
    //先读到一键开机的结果，应答报文错位，流程混乱，后续应当由模组修改保证指令应答的准确性，add by hcq, 20230607
    if((1 == get_onekey_powerup_flag(dev_param))&&(15*1000 > fp_get_increment_of_time_ms(get_onekey_powerup_tv_time(dev_param))))
    {

        WD_LOG("received one key power up identify result.\n");
        //memcpy(identify_result_id, get_onekey_powerup_search_id(), get_onekey_powerup_search_num());
        for(int count = 0; count < get_onekey_powerup_search_num(dev_param); count++)
        {
            identify_result_id[count] = get_onekey_powerup_search_id(dev_param)[count];
        }
        set_onekey_powerup_flag(dev_param, 0);
        WD_DBG("sleep 700ms\n");
        usleep(700 * 1000);
        goto GDBUS_IDENTIFY_WITH_MULTIPLE_USER_PT_DEAL_WITH_RESULT_ID;//若为一键开机结果，则直接跳转到处理结果
    }
    set_onekey_powerup_flag(dev_param, 0);

    gettimeofday(&tv_begin, NULL);

    found_result = -1;

    if(DRV_OK != fp_auto_identify(dev_param, 3, identify_id, FP_CURRENT_OS_TYPE, identify_result_id, 1000))
    {
        switch(fp_get_ctrlFlag(dev_param))
        {
            case FP_CONTROL_FLAG_STOPPED:
                WD_DBG("FP_CONTROL_FLAG_STOPPED\n");
                break;
            case FP_CONTROL_FLAG_TIMEOUT:
                WD_DBG("FP_CONTROL_FLAG_TIMEOUT\n");
                break;
            case FP_CONTROL_FLAG_DEV_NOT_EXIST://与设备失联
                WD_DBG("FP_CONTROL_FLAG_DEV_NOT_EXIST\n");
                break;
            default:
                WD_DBG("OPS_VERIFY_ERROR\n");
                break;
        }

        fp_cancel(dev_param);
        //fp_read_invalid_pkg(dev_param, 3);//规避取消报文错位，add by hcq, 20230314
        fp_set_ctrlFlag(dev_param, FP_CONTROL_FLAG_IDLE);
        ofp_identify_with_multiple_user_status_callback(NULL);
        goto GDBUS_IDENTIFY_WITH_MULTIPLE_USER_PT_END;
    }
    fp_cancel(dev_param);

GDBUS_IDENTIFY_WITH_MULTIPLE_USER_PT_DEAL_WITH_RESULT_ID:


    for(int n = 0; n < ENROLL_NUM_MAX; n++)
    {
        if(0xffff == identify_result_id[n])
        {
            ofp_identify_with_multiple_user_status_callback(NULL);
            break;
        }

        ofp_find_fprint_info_byfprintid(dev, identify_result_id[n], &fprint_found);


        if(NULL != fprint_found)
        {
            found_result = 0;
#if 1
            ofp_identify_with_multiple_user_status_callback(fprint_found->user_id);
#else //uos验证一键开机启动时验证通过，但未进入系统桌面，测试多发送几次是否能进入
            gettimeofday(&tv_end, NULL);

            if(tv_end.tv_usec > tv_begin.tv_usec)
            {
                verify_time_ms = (tv_end.tv_sec - tv_begin.tv_sec)*1000 +\
                    (tv_end.tv_usec - tv_begin.tv_usec)/1000;
            }
            else
            {
                verify_time_ms = (tv_end.tv_sec - tv_begin.tv_sec - 1)*1000 +\
                    (tv_end.tv_usec + 1000*1000 - tv_begin.tv_usec)/1000;
            }

            D_DBG("verify_time_ms = %d\n", verify_time_ms);

            if(80 > verify_time_ms)//测试50ms内完成一键开机指纹搜索结果读取，增加到80ms降低风险
            {
                usleep(600 * 1000);//休眠600ms
            }
            ofp_identify_with_multiple_user_status_callback(fprint_found->user_id);
#endif
            goto GDBUS_IDENTIFY_WITH_MULTIPLE_USER_PT_END;
        }
    }

    if(0 != found_result)
    {
        WD_DBG("user_id = NULL\n");
        ofp_identify_with_multiple_user_status_callback(NULL); //返回不匹配
    }

GDBUS_IDENTIFY_WITH_MULTIPLE_USER_PT_END:
    fp_set_ctrlFlag(dev_param, FP_CONTROL_FLAG_IDLE);
    if(CONTROL_FLAG_STOPING == priv->ctrlFlag)
    {
        priv->ctrlFlag = CONTROL_FLAG_STOPPED;
    }
    usb_dev_close(usb_dev);
    ofp_set_dev_status (dev, DEVS_COMM_IDLE);
    free(p0);
    free(p1);
    g_slist_free(argv);
    DBG("gdbus_identify_with_multiple_user_pt<=======================exit\n");

}




static gboolean gdbus_handle_identify_with_multiple_user(OfprintSkeleton* skeleton,
                                            GDBusMethodInvocation *invocation)
{
    DBG("gdbus_handle_identify_with_multiple_user ===================>enter\n");
    WD_DBG("start.\n");

    int err = 0;
    pthread_t thr;

    GSList *argv = NULL;
    OfprintSkeleton **p0;
    GDBusMethodInvocation **p1;

    p0 = malloc(sizeof(void *));
    memcpy(p0, &skeleton, sizeof(void *));
    argv = g_slist_append(argv, p0);

    p1 = malloc(sizeof(void *));
    memcpy(p1, &invocation, sizeof(void *));
    argv = g_slist_append(argv, p1);

    err = pthread_create(&thr, NULL, (void *)gdbus_identify_with_multiple_user_pt, argv);

    if (err != 0) {
        WD_ERR(_("Can't create thread: %s\n"), strerror(err));
    }
    DBG("gdbus_handle_identify_with_multiple_user <===================exit\n");

    return TRUE;
}

void gdbus_stop_identify_with_multiple_user_pt(GSList * argv)
{
    DBG("gdbus_stop_identify_with_multiple_user_pt =======================>enter\n");
    WD_DBG("start.\r\n");

    OfprintSkeleton **p0;
    GDBusMethodInvocation **p1;

    p0 = g_slist_nth_data(argv,0);
    p1 = g_slist_nth_data(argv,1);

    OfprintSkeleton *skeleton = (OfprintSkeleton *)*p0;
    GDBusMethodInvocation *invocation = (GDBusMethodInvocation *)*p1;
    ofp_dev *dev = dev_ofprint;
    driver_info *priv = (driver_info *)dev->dev_priv;
    FP_DEVICE_PARAM_STRUCT *dev_param = &(priv->fp_device_param);
    int timeout = 3 * 1000;
    int timeused = 0;

    if((dev->enable == FALSE) || (0 >= dev->dev_num))
    {
        goto GDBUS_STOP_IDENTIFY_WITH_MULTIPLE_USER_PT_END;
    }

    if(ofp_get_dev_status(dev) == DEVS_COMM_IDLE)    // 如果设备为空闲状态
    {
        WD_DBG("DEVS_COMM_IDLE.\n");
        goto GDBUS_STOP_IDENTIFY_WITH_MULTIPLE_USER_PT_END;
    }

    WD_DBG("start.\n");

    // 设置状态位，用于通知用户中断
    priv->ctrlFlag = CONTROL_FLAG_STOPING;
    fp_set_ctrlFlag(dev_param, FP_CONTROL_FLAG_STOPPED);

    while ((priv->ctrlFlag != CONTROL_FLAG_STOPPED) &&
        (priv->ctrlFlag != CONTROL_FLAG_DONE) &&
        (priv->ctrlFlag != CONTROL_FLAG_IDLE) &&
        (timeused < timeout) &&
        (ofp_get_dev_status(dev) != DEVS_COMM_IDLE))
    {
        timeused += 10;//EM1600DEV_FINGER_CHECK_INTERVAL_MS;
        usleep(10 * 1000);//usleep(EM1600DEV_FINGER_CHECK_INTERVAL_MS * 1000);
    }

GDBUS_STOP_IDENTIFY_WITH_MULTIPLE_USER_PT_END:
    if ((priv->ctrlFlag == CONTROL_FLAG_STOPPED)
        || (priv->ctrlFlag == CONTROL_FLAG_DONE)
        || (ofp_get_dev_status(dev) == DEVS_COMM_IDLE))
    {
        priv->ctrlFlag == CONTROL_FLAG_IDLE;
    }

    DBG("gdbus_stop_identify_with_multiple_user_pt <=======================exit\n");
    ofprintx_complete_stop_verify(skeleton, invocation);
    free(p0);
    free(p1);
    g_slist_free(argv);
}


static gboolean gdbus_handle_stop_identify_with_multiple_user(OfprintSkeleton* skeleton,
                                            GDBusMethodInvocation *invocation)
{
    DBG("gdbus_handle_stop_identify_with_multiple_user==================>enter\n");
    WD_DBG("start.\r\n");

    int err = 0;
    pthread_t thr;

    GSList *argv = NULL;
    OfprintSkeleton **p0;
    GDBusMethodInvocation **p1;

    p0 = malloc(sizeof(void *));
    memcpy(p0, &skeleton, sizeof(void *));
    argv = g_slist_append(argv, p0);

    p1 = malloc(sizeof(void *));
    memcpy(p1, &invocation, sizeof(void *));
    argv = g_slist_append(argv, p1);

    err = pthread_create(&thr, NULL, (void *)gdbus_stop_identify_with_multiple_user_pt, argv);

    if (err != 0) {
        WD_ERR("Can't create thread: %s\n", strerror(err));
    }
    DBG("gdbus_handle_stop_identify_with_multiple_user<==================exit\n");

    return TRUE;

}




static void gdbus_signal_enroll_status(char *id, int code, char *msg)
{
    WD_DBG("start.\r\n");
    ofprintx_emit_enroll_status(pSkeleton, id, code, msg);
    //WD_DBG("end.\r\n");
}

static void gdbus_signal_verify_status(char *id, int code, char *msg)
{
    WD_DBG("start.\r\n");
    if (msg == NULL)
    {
        ofprintx_emit_verify_status(pSkeleton, id, code, "");
    } else {
        ofprintx_emit_verify_status(pSkeleton, id, code, msg);
    }

    //WD_DBG("end.\r\n");
}

static void gdbus_signal_touch(char *id, gboolean pressed)
{
    WD_DBG("start.\r\n");
    ofprintx_emit_touch(pSkeleton, id, pressed);
    WD_DBG("end.\r\n");
}

static void gdbus_identify_with_multiple_user_status(char *uuid)
{
    WD_DBG("start.\r\n");
    ofprintx_emit_identify_with_multiple_user_status(pSkeleton, uuid);
    WD_DBG("end.\r\n");
}


int ofp_set_dev_state(uint8 state)
{
    if(DeviceStateNormal & state)
    {
        WD_LOG("DeviceStateNormal\r\n");
        ofprintx_set_state(pSkeleton, state);
    }
    return 0;
}


void GBusAcquired_Callback (GDBusConnection *connection,
    const gchar *name,
    gpointer user_data)
{
    ofp_dev *dev = dev_ofprint;
    driver_info *priv = (driver_info *)dev->dev_priv;
    GError *error = NULL;


    WD_DBG("GBusAcquired_Callback has been invoked\n");
    //printf("GBusAcquired_Callback the name = %s\n",name);
    //printf("GBusAcquired_Callback the user_data = %s\n",(char*)user_data);

    pSkeleton =  ofprintx_skeleton_new ();
    g_signal_connect(pSkeleton,"handle-claim",G_CALLBACK(gdbus_handle_claim),NULL);
    g_signal_connect(pSkeleton,"handle-enroll",G_CALLBACK(gdbus_handle_enroll),NULL);
    g_signal_connect(pSkeleton,"handle-stop-enroll",G_CALLBACK(gdbus_handle_stop_enroll),NULL);
    g_signal_connect(pSkeleton,"handle-verify",G_CALLBACK(gdbus_handle_verify),NULL);
    g_signal_connect(pSkeleton,"handle-stop-verify",G_CALLBACK(gdbus_handle_stop_verify),NULL);
    g_signal_connect(pSkeleton,"handle-delete-finger",G_CALLBACK(gdbus_handle_delete_finger),NULL);
    g_signal_connect(pSkeleton,"handle-delete-all-fingers",G_CALLBACK(gdbus_handle_delete_all_fingers),NULL);
    g_signal_connect(pSkeleton,"handle-list-fingers",G_CALLBACK(gdbus_handle_list_fingers),NULL);
    g_signal_connect(pSkeleton,"handle-rename-finger",G_CALLBACK(gdbus_handle_rename_finger),NULL);
    g_signal_connect(pSkeleton,"handle-identify-with-multiple-user",G_CALLBACK(gdbus_handle_identify_with_multiple_user),NULL);
    g_signal_connect(pSkeleton,"handle-stop-identify-with-multiple-user",G_CALLBACK(gdbus_handle_stop_identify_with_multiple_user),NULL);

    ofp_enroll_status_callback = gdbus_signal_enroll_status;
    ofp_verify_status_callback = gdbus_signal_verify_status;
    ofp_touch_callback = gdbus_signal_touch;
    ofp_identify_with_multiple_user_status_callback = gdbus_identify_with_multiple_user_status;

    ofprintx_set_name(pSkeleton, dev->device_name);
    if(1 == get_upgrade_state())
    {
        WD_LOG("device state = 0x%02x\n", DeviceStateNormal);
        ofprintx_set_state(pSkeleton, DeviceStateNormal);
    }
    else
    {
        WD_LOG("device state = 0x%02x\n", priv->dev_state);
        ofprintx_set_state(pSkeleton, priv->dev_state);
    }
    ofprintx_set_type_(pSkeleton, DeviceTypeTouch);
    ofprintx_set_capability(pSkeleton, DeviceCapAutologin);

    (void) g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(pSkeleton),
                                            connection,
                                            OMS_GDBUS_OFP_OBJECT_PATH,
                                            &error);

    if(error != NULL){
        g_print("Error: Failed to export object. Reason: %s.\n", error->message);
        g_error_free(error);
        g_main_loop_quit(pLoop);
    }
}

void GBusNameAcquired_Callback (GDBusConnection *connection,
    const gchar *name,
    gpointer user_data)
{
    WD_LOG(_("name_acquired_cb called, Acquired bus name: %s\n"), OMS_GDBUS_OFP_BUS_NAME);
}

void GBusNameLost_Callback (GDBusConnection *connection,
    const gchar *name,
    gpointer user_data)
{
    WD_DBG(_("GBusNameLost_Callback has been invoked******\n"));
    //g_main_loop_quit(pLoop);
}



int main(int argc,char* argv[])
{
    ofp_dev * dev = NULL;
    int ret = 0;
    pthread_t thr_upgrade;
    int err = 0;

    check_log_file_size();

    if(0 != ofp_conf_init())
    {
        WD_ERR("ofp_conf_init failed!!!\n");
        return -1;
    }

    ofp_dev_init();
    dev = dev_ofprint;
    driver_info *priv = (driver_info *)dev->dev_priv;
    FP_DEVICE_PARAM_STRUCT *dev_param = &(priv->fp_device_param);
    USB_DEV_STRUCT *usb_dev = &(dev_param->usb_dev);
    INTF_USB_ID_STRUCT *id_table = (INTF_USB_ID_STRUCT *)(dev->usb_info.id_table);

    WD_DBG("driver start.\n");

    ret = usb_lib_init(dev);
    if(0 > ret)
    {
        WD_DBG("libusb_init failed.\n");
        return -1;
    }

    usb_set_autosuspend_flag(usb_dev, priv->config.autosuspend_flag);

    ofp_drv_init(dev);
    if(0 < dev->ops_discover(dev))
    {
        priv->dev_state |= DeviceStateNormal;
        ofp_onekey_powerup_identify(dev);

        if(0 != priv->mode_flag)
            ofp_set_mode(dev);

        if(OFP_SET_REBOOT_FLAG == priv->reboot_flag)
            ofp_set_reboot(dev);

        WD_DBG("DeviceStateNormal=====================\n");
    }
    else
    {
        priv->dev_state &=~ DeviceStateNormal;
        WD_LOG("not discover the device.\n");
        ofp1234_upgrade_pt(dev, 0);
    }

    ofp1234_fw_version_manager(dev);

    ofp_get_fprint_list(dev);

    pLoop = g_main_loop_new(NULL, FALSE);

    guint own_id =
    g_bus_own_name (OMS_GDBUS_OFP_BUS_TYPE,
        OMS_GDBUS_OFP_BUS_NAME,
        G_BUS_NAME_OWNER_FLAGS_NONE,//G_BUS_NAME_OWNER_FLAGS_REPLACE|G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT,//
        GBusAcquired_Callback,
        GBusNameAcquired_Callback,
        GBusNameLost_Callback,
        NULL,
        NULL);

    /* * emit my signal1 every 1 second to trigger example communication */
    //g_timeout_add(3000, (GSourceFunc)Emit_Test_Status, NULL);

    g_main_loop_run(pLoop);
    g_main_loop_unref(pLoop);

    g_bus_unown_name(own_id);

    libusb_hotplug_deregister_callback(dev_ofprint->ctx, (dev_ofprint->usb_info.callback_handle)[1]);

    libusb_hotplug_deregister_callback(dev_ofprint->ctx, (dev_ofprint->usb_info.callback_handle)[0]);

    usb_lib_exit(dev_ofprint);
    ofp_dev_free(dev_ofprint);

    return 0;
}

